package com.kingre.et.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.mail.MessagingException;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.providers.encoding.PasswordEncoder;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;

import com.kingre.et.Constants;
import com.kingre.et.dao.IRawdataDAO;
import com.kingre.et.dao.IRoleDAO;
import com.kingre.et.dao.ISchoolDAO;
import com.kingre.et.dao.IUserDAO;
import com.kingre.et.model.Rawdata;
import com.kingre.et.model.Role;
import com.kingre.et.model.School;
import com.kingre.et.model.User;
import com.kingre.et.service.IQuestionService;
import com.kingre.et.service.IUserService;
import com.kingre.et.util.MailUtil;

@Transactional
public class UserServiceImpl implements IUserService, UserDetailsService {

    private static final Logger logger = Logger.getLogger(UserServiceImpl.class);
    @Autowired
    private IUserDAO userDAO;
    @Autowired
    private ISchoolDAO schoolDAO;
    @Autowired
    private IRoleDAO roleDAO;
    @Autowired
    private IRawdataDAO rawdataDAO;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private IQuestionService questionService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
        User user = userDAO.findByUsername(username);

        if (user == null) {
            throw new UsernameNotFoundException("User " + username + " has no GrantedAuthority");
        }
        user.getRole().getName();
        return user;
    }

    @Override
    public List<School> findSchoolAll() {
        List<School> list = schoolDAO.findAll();
        if (list == null)
            return null;
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getSchoolType() != 10) {
                list.remove(i--);
            }
        }
        return list;
    }

    @Override
    public User register(User user) {
        Role role = roleDAO.findByNameExact(Constants.USER_ROLE);
        user.setRole(role);
        user.setStatusCode(Constants.USER_STATUS_CODE_ENABLE);
        user.setPassword(passwordEncoder.encodePassword(user.getPassword(), null));
        // logger.debug("passwordEncoder =" + passwordEncoder);
        // user.setPassword(passwordEncoder.encodePassword(user.getPassword(),
        // null));
        userDAO.save(user);
        return user;
    }

    @Override
    public boolean isQuestionFinish(Integer userId) {
        User user = userDAO.get(userId);
        return user.getRawdata() != null && user.getRawdata().size() >= Constants.COUNT_QUESTION;

    }

    @Override
    public void sendMail(String email, String subject, String message) throws IOException, MessagingException {
        message = message.replace("@", "$");

        logger.debug("email.address =" + email);
        logger.debug("email.subject =" + subject);
        logger.debug("email.message =" + message);

        MailUtil mail = new MailUtil(email, subject, message);
        mail.sendMail();
    }

    @Override
    public String activeRegister(Integer userId, String email) {
        User user = userDAO.get(userId);
        if (user == null || !user.getEmail().equals(email) || user.getStatusCode() != 0)
            return null;
        else {
            String password = user.getPassword();
            user.setStatusCode(Constants.USER_STATUS_CODE_ENABLE);
            user.setPassword(passwordEncoder.encodePassword(user.getPassword(), null));
            return password;
        }
    }

    @Override
    public School getSchool(Integer id) {
        return schoolDAO.get(id);
    }

    @Override
    public List<User> findUserBySchoolAndName(Integer schoolId, String name) {
        logger.debug("schoolId =" + schoolId);
        List<User> users;
        if (schoolId == -1)
            users = userDAO.findByName(Constants.USER_ROLE, name);
        else {
            School school = schoolDAO.get(schoolId);
            if (school.getSchoolType() == 20)
                users = userDAO.findByNameAndSchool(Constants.USER_ROLE, school, name);
            else {
                users = userDAO.findByNameAndSubSchool(Constants.USER_ROLE, school, name);
            }
        }
        if (users != null)
            for (User u : users) {
                u.isTestFinish();
            }
        return users;
    }

    @Override
    public List<User> findAccounts() {
        List<User> users = userDAO.findAccounts(Constants.USER_ROLE);
        if (users == null)
            return null;
        for (User u : users) {
            u.getRole().getName();
            School school = u.getSchool();
            if (school != null)
                school.getName();
        }
        return users;
    }

    @Override
    public void delete(Integer id) {
        User user = userDAO.get(id);
        userDAO.delete(user);
    }

    @Override
    public void add(User user, Integer schoolId) {
        if (user == null)
            return;
        School s = schoolDAO.get(schoolId);
        user.setPassword(passwordEncoder.encodePassword(user.getPassword(), null));
        user.setSchool(s);
        Role r = roleDAO.findByNameExact(Constants.TEACHER_ROLE);
        user.setRole(r);
        user.setStatusCode(1);
        userDAO.save(user);
    }

    @Override
    public void updatePasswrod(User currentUser, String password) {
        User user = userDAO.get(currentUser.getId());
        user.setPassword(passwordEncoder.encodePassword(password, null));
        currentUser.setPassword(passwordEncoder.encodePassword(password, null));
    }

    // public void insertData() {
    // Role role = roleDAO.findByNameExact(Constants.USER_ROLE);
    // for (int i = 0; i < 120; i++) {
    // User user = new User();
    // String name = "T" + String.valueOf(RandomUtils.nextInt(100000));
    // String email = name + "@" + String.valueOf(RandomUtils.nextInt(1000)) +
    // ".com";
    // if (userDAO.findByUsername(email) != null)
    // continue;
    // user.setEmail(email);
    // user.setPassword(passwordEncoder.encodePassword("123456", null));
    // user.setName(name);
    // user.setSex(RandomUtils.nextBoolean() ? 10 : 20);
    // user.setDegree(Math.random() < 0.35 ? 10 : (RandomUtils.nextBoolean() ?
    // 20 : 30));
    // user.setGrade(RandomUtils.nextBoolean() ? 1 : 0);
    // user.setMajor(Math.random() < 0.35 ? 10 : (RandomUtils.nextBoolean() ? 20
    // : 30));
    // user.setStudentId(String.valueOf(RandomUtils.nextInt()));
    // user.setStatusCode(1);
    // user.setRole(role);
    // List<School> sub =
    // schoolDAO.findSubSchool(schoolDAO.get(RandomUtils.nextBoolean() ? 1 :
    // 2));
    // for (School s : sub) {
    // logger.debug("s =" + s);
    // }
    // user.setSchool(sub.get(RandomUtils.nextInt(sub.size())));
    // userDAO.save(user);
    //
    // for (int id = 1; id <= 48; id++) {
    // int value = (int) (Math.random() * 10) + 1;
    // value = value > 5 ? (value - 5) : value;
    // Rawdata rawdata = new Rawdata(user, id, value, new Date());
    // rawdataDAO.save(rawdata);
    // }
    // // questionService.conversionAndSaveTdata(user);
    // }
    // }

    @Override
    public boolean usernameExist(String username) {
        User user = userDAO.findByUsername(username);
        return user != null;
    }

    @Override
    public boolean studentIdExist(String studentId, School school) {
        User user = userDAO.findByStudentId(studentId, school.getOverSchool());
        return user != null;
    }

    @Override
    public School findSchool(Integer userId) {
        User user = userDAO.get(userId);
        School school = user.getSchool();
        if (userDAO.findByNameAndSchool(Constants.USER_ROLE, school, "").size() > Constants.SCHOOL_REPORT_NUM)
            school.setStatReport(true);
        return school;
    }

    @Override
    public List<School> findSubSchool(Integer schoolId) {
        School school = schoolDAO.get(schoolId);
        List<School> list = schoolDAO.findSubSchool(school);
        return list;
    }

    @Override
    public List<Map<String, String>> findRawdataAll() {
        List<Rawdata> list = rawdataDAO.findAll();
        if (list == null)
            return null;
        List<Map<String, String>> data = new ArrayList<Map<String, String>>();
        Map<String, String> map = null;
        for (int i = 0; i < list.size(); i++) {
            if (map == null) {
                map = new HashMap<String, String>();
            } else if (list.get(i).getUser().getId().intValue() == Integer.parseInt(map.get("id") == null ? "0" : map
                    .get("id"))) {
                map.put("question_" + list.get(i).getQuestion().getId(), list.get(i).getOriginalScore().toString());
                continue;
            } else {
                data.add(map);
                map = new HashMap<String, String>();
            }

            map.put("id", list.get(i).getUser().getId().toString());
            map.put("name", list.get(i).getUser().getName());
            map.put("sex", list.get(i).getUser().getSex().toString());
            map.put("degree", list.get(i).getUser().getDegree().toString());
            map.put("age", list.get(i).getUser().getAge().toString());
            map.put("major", list.get(i).getUser().getMajor().toString());
            map.put("studentId", list.get(i).getUser().getStudentId());
            map.put("email", list.get(i).getUser().getEmail());
            map.put("subName", list.get(i).getUser().getSchool().getName());
            map.put("schoolName", list.get(i).getUser().getSchool().getOverSchool().getName());

            map.put("question_" + list.get(i).getQuestion().getId(), list.get(i).getOriginalScore().toString());
        }
        data.add(map);
        logger.debug("data.length =" + data.size());
        return data;
    }

    @Override
    public User getUserByEmail(String email) {
        return userDAO.findByEmail(email);
    }

    @Override
    public void updatePwd(Integer id, String pwd) {
        User user = userDAO.get(id);
        user.setPassword(passwordEncoder.encodePassword(pwd, null));
    }

    @Override
    public boolean emailExist(String email) {
        User user = userDAO.findByEmail(email);
        return user != null;
    }

}
